from datetime import datetime
from typing import List, Union, Optional

from odoo.addons.basic_configuration.config.env_config import switch_env
from pydantic import BaseModel, Field, root_validator, validator

from odoo.addons.pay_connector.config.pay_config import switched_env

"""
Config 配置
"""


class CountryGroup(BaseModel):
    """
    对应【res.country.group】地区组
    """
    id: int = Field(None, description='地区组ID')
    name: str = Field(None, description='名称')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
        return values


class CustomerCategory(BaseModel):
    """
    对应【rp.customer.category】 客户分类
    """
    id: int = Field(None, description='分类ID')
    name: str = Field(None, description='分类名称')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get("__from_odoo")
        env = values.get("__env")
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
        return values


class CustomerLevel(BaseModel):
    """
    对应【rp.customer.level】 客户等级
    """
    id: int = Field(None, description='客户等级ID')
    name: str = Field(None, description='等级名称')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
        return values


class UomUom(BaseModel):
    """
    对应【uom.uom】 单位
    """
    id: int = Field(None, description='单位ID')
    name: str = Field(None, description='名称')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
        return values


class RpBookTime(BaseModel):
    """
    对应【rp.book.time】  预约时段
    """
    id: int = Field(None, description='预定时段ID')
    name: str = Field(None, description='预定时段')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
        return values


class RpCourierPostalOutlet(BaseModel):
    """
    对应【rp.courier.postal.outlet】 承运商网点
    """
    id: int = Field(None, description='网点ID')
    name: str = Field(None, description='网点名称')
    country: 'Country' = Field(None, description='国家')
    zip: str = Field(None, description='邮编')
    type: str = Field(None, description='类型')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['country'] = Country(__from_odoo=mdl.country_id, __env=env)
            values['zip'] = mdl.zip
            values['type'] = mdl.type
        return values


class PackageType(BaseModel):
    """
    对应【rp.package.type】 包裹类型
    """
    id: int = Field(None, description='包裹类型ID')
    name: str = Field(None, description='包裹类型')
    picture_url: str = Field(None, description='图标URL')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            base_url = switch_env.get('env').get('server')
            picture_url = '%s/web/image?model=rp.icon&id=%s&field=photo' % (base_url, mdl.package_icon_id.id)
            if mdl.package_icon_id.selected_icon:
                picture_url = '%s/web/image?model=rp.icon&id=%s&field=selected_icon' % (base_url, mdl.package_icon_id.id)
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['picture_url'] = picture_url
        return values


class Currency(BaseModel):
    """
    对应 【res.currency】货币单位
    """
    id: int = Field(None, description='ID')
    name: str = Field(None, description='币种')
    full_name: str = Field(None, description='名称')
    symbol: str = Field(None, description='符号')
    position: str = Field(None, description='符号位置')

    @root_validator(pre=True)
    def create(cls, values):
        """
        货币单位
        """
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['full_name'] = mdl.full_name
            values['symbol'] = mdl.symbol
            values['position'] = mdl.position
        return values


class Aging(BaseModel):
    """
    时效
    """
    id: int = Field(None, description='ID')
    name: str = Field(None, description="名称")
    type: str = Field(None, description="类型")
    value: float = Field(None, description='数值')
    uom_uom: UomUom = Field(None, description='单位')
    standard_unit_time: float = Field(None, description='标准单位时间')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['type'] = mdl.type
            values['value'] = mdl.standard_unit_time
            values['uom_uom'] = UomUom(__from_odoo=mdl.time_uom_id, __env=env)
            values['standard_unit_time'] = mdl.standard_unit_time
        return values


class Date(BaseModel):
    """
     日期,存放年月日
    可以单传字符串格式，会自动存储时间戳格式，使用方式：Date(str_format="2023-03-25")
    可以单传时间戳格式，会自动转存字符串格式，使用方式：Date(stamp_format=1679827200)
    """
    str_format: Optional[str] = Field(None, description='日期字符串格式，如YYYY-MM-DD')
    stamp_format: Optional[int] = Field(None, description='日期的Unix时间戳格式')

    @validator('str_format', 'stamp_format', pre=True, always=True)
    def validate_date(cls, v, values, field):
        if field.name == 'str_format' and v is not None:
            date = datetime.strptime(v, '%Y-%m-%d').date()
            values['stamp_format'] = int(date.timestamp())
            return v
        elif field.name == 'stamp_format' and v is not None:
            values['str_format'] = datetime.fromtimestamp(v).strftime('%Y-%m-%d')
            return v
        return v


class DateTime(BaseModel):
    """
    时间,存放年月日时分秒
    可以单传字符串格式，会自动存储时间戳格式，使用方式：DateTime(str_format="2023-03-25 16:43:00")
    可以单传时间戳格式，会自动转存字符串格式，使用方式：DateTime(stamp_format=1679827200)
    """
    str_format: Optional[str] = Field(None, description='日期时间字符串格式，如YYYY-MM-DD HH:MM:SS')
    stamp_format: Optional[int] = Field(None, description='日期时间的Unix时间戳格式')

    @validator('str_format', 'stamp_format', pre=True, always=True)
    def validate_datetime(cls, v, values, field):
        if field.name == 'str_format' and v is not None:
            # 解析日期时间字符串
            datetime_obj = datetime.strptime(v, '%Y-%m-%d %H:%M:%S')
            # 确保时间戳是同步更新的
            values['stamp_format'] = int(datetime_obj.timestamp())
            return datetime_obj.strftime('%Y-%m-%d %H:%M:%S')
        elif field.name == 'stamp_format' and v is not None:
            # 从时间戳转换
            values['str_format'] = datetime.fromtimestamp(v).strftime('%Y-%m-%d %H:%M:%S')
            return v
        return v


"""
Main
"""


class User(BaseModel):
    """
    用户
    """
    id: int = Field(None, description='用户ID')
    name: str = Field(None, description='用户名')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
        return values


class Shipper(BaseModel):
    """
    托运商
    """
    id: int = Field(None, description='托运商ID')
    name: str = Field(None, description='名称')
    code: str = Field(None, description='编号')
    photo_url: str = Field(None, description='托运商图片')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['code'] = mdl.code
            values['photo_url'] = f'http://admin.rectaparcel.com/web/image?model=rp.courier&id={mdl.id}&field=photo'
        return values


class Courier(BaseModel):
    """
    对应【rp.courier】 承运商
    """
    id: int = Field(None, description='承运商ID')
    name: str = Field(None, description='承运商名称')
    code: str = Field(None, description='承运商编码')
    photo_url: str = Field(None, description='承运商图片')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['code'] = mdl.code
            values['photo_url'] = f'http://admin.rectaparcel.com/web/image?model=rp.courier&id={mdl.id}&field=photo'
        return values


class ValueAdded(BaseModel):
    """
    对应【rp.value.added.service】 增值服务
    """
    id: int = Field(None, description='增值服务ID')
    name: str = Field(None, description='名称')
    type: str = Field(None, description='类型')
    category: str = Field(None, description='增值服务分类')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['type'] = mdl.type
            values['category'] = mdl.category
        return values


class PriceAdjustRule(BaseModel):
    """
    对应 【rp.price.adjust.rule】 调价规则
    """
    id: int = Field(None, description='ID')
    name: str = Field(None, description='名称')
    rule: str = Field(None, description='规则')
    changed_price: float = Field(None, description='改后价格')
    fixed_float: float = Field(None, description='固定浮动')
    rated_float: float = Field(None, description='比率浮动')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['rule'] = mdl.rule
            values['changed_price'] = mdl.changed_price
            values['fixed_float'] = mdl.fixed_float
            values['rated_float'] = mdl.rated_float
        return values


class RPSalePriceAdjust(BaseModel):
    """
    对应【rp.shipper.sale.price.adjustment】销售调价
    """
    id: str = Field(None, description='ID')
    name: str = Field(None, description='名称')
    code: str = Field(None, description='编码')
    adjust_for: str = Field(None, description='调价对象')
    price_adjust_rule_id: 'PriceAdjustRule' = Field(None, description='条件规则')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['code'] = mdl.code
            values['adjust_for'] = mdl.adjust_for
            values['price_adjust_rule_id'] = PriceAdjustRule(__from_odoo=mdl.price_adjust_rule_id, __env=env)
        return values


class VolumeWeight(BaseModel):
    """
    对应【rp.volume.weight】体积重
    """
    id: int = Field(None, description='体积重ID')
    value: float = Field(None, description='数值')
    uom_id: UomUom = Field(None, description='单位')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['value'] = mdl.volume_weight
            values['uom_id'] = UomUom(__from_odoo=mdl.volume_weight_uom_id, __env=env)
        return values


class Item(BaseModel):
    """
    对应【rp.item】下属物品
    """
    id: int = Field(None, description='物品ID')
    name: str = Field(None, description='物品名称')
    type: str = Field(None, description='类型')
    product_country_id: 'Country' = Field(None, description='国家')
    quantity: int = Field(None, description='数量')
    quantity_uom_id: UomUom = Field(None, description='数量单位')
    value: float = Field(None, description='单个价值')
    weight: float = Field(None, description='单个重量')
    weight_uom_id: UomUom = Field(None, description='重量单位')
    hs_code: str = Field(None, description='海关编码')
    desc: str = Field(None, description='描述')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['type'] = mdl.type
            values['product_country_id'] = Country(__from_odoo=mdl.product_country_id, __env=env)
            values['quantity'] = mdl.quantity
            values['quantity_uom_id'] = UomUom(__from_odoo=mdl.quantity_uom_id, __env=env)
            values['value'] = mdl.value
            values['weight'] = mdl.weight
            values['weight_uom_id'] = UomUom(__from_odoo=mdl.weight_uom_id, __env=env)
            values['hs_code'] = mdl.hs_code
            values['desc'] = mdl.desc
        return values


"""
Region
"""


class Country(BaseModel):
    """
    对应【res.country】 国家
    """
    id: int = Field(None, description='国家ID')
    name: str = Field(None, description='国家名称')
    short_name: str = Field(None, description='国家简称')
    phone_code: str = Field(None, description='长途编号')
    picture_url: str = Field(None, description='国家URL')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get("__from_odoo")
        env = values.get("__env")
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['short_name'] = mdl.code
            values['phone_code'] = mdl.phone_code
            values['picture_url'] = switched_env.get('env').get('server') + mdl.image_url if mdl.image_url else ''
        return values


class State(BaseModel):
    """
    对应【res.country.state】 省
    """
    id: int = Field(None, description='省ID')
    name: str = Field(None, description='省名称')
    country_id: Country = Field(None, description='国家')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['country_id'] = Country(__from_odoo=mdl.country_id, __env=env)
        return values


class City(BaseModel):
    """
    对应【res.city】 城市
    """
    id: int = Field(None, description='城市ID')
    name: str = Field(None, description='城市名称')
    country_id: Country = Field(None, description='国家')
    state_id: State = Field(None, description='省')

    @root_validator(pre=True)
    def create(cls, values):
        mdl = values.get('__from_odoo')
        env = values.get('__env')
        if mdl and env:
            values['id'] = mdl.id
            values['name'] = mdl.name
            values['country_id'] = Country(__from_odoo=mdl.country_id, __env=env)
            values['state_id'] = State(__from_odoo=mdl.state_id, __env=env)
        return values


class County(BaseModel):
    """
    对应【res.county】 县
    """
    id: int = Field(None, description='县ID')
    name: str = Field(None, description='县名称')
    city: City = Field(None, description='城市')
    state: State = Field(None, description='省')
    country: Country = Field(None, description='国家')

    @root_validator(pre=True)
    def create(cls, values):
        env = values.get('__env')
        mdl = values.get('__from_odoo')
        if mdl and env:
            values['id'] = mdl.get('id')
            values['name'] = mdl.get('name')
            values['city'] = City(__from_odoo=mdl.city_id, __env=env)
            values['state'] = State(__from_odoo=mdl.state_id, __env=env)
            values['country'] = Country(__from_odoo=mdl.country_id, __env=env)
        return values
